home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Utilities / uupc 3.1 / (uupc π) / dcpsys.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-02  |  41.1 KB  |  1,712 lines  |  [TEXT/KAHL]

  1.  
  2.  
  3. /*            dcpsys.c
  4.  
  5.             Revised edition of dcp
  6.  
  7.             Stuart Lynne May/87
  8.  
  9.             Copyright (c) Richard H. Lamb 1985, 1986, 1987
  10.             Changes Copyright (c) Stuart Lynne 1987
  11.             Portions Copyright © David Platt, 1992, 1991.  All Rights Reserved
  12.             Worldwide.
  13.  
  14. */
  15. /* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */
  16. /* Get the next system, and other support routines  */
  17. #include "dcp.h"
  18. #include <string.h>
  19. #include <Serial.h>
  20. /*#define PROTOS  "trkg"*/
  21. #define PROTOS  "gfG"
  22. #define MAXLOGTRY       3
  23.  
  24. Proto Protolst[] = {
  25.         'g', ggetpkt, gsendpkt, gopenpk, gclosepk, gfilepkt, geofpkt, grdmsg,  gwrmsg, gsendresp,
  26.         'f', fgetpkt, fsendpkt, fopenpk, fclosepk, ffilepkt, feofpkt, frdmsg,  fwrmsg, fsendresp,
  27.         'G', ggetpkt, gsendpkt, gopenpk, gclosepk, gfilepkt, geofpkt, grdmsg,  gwrmsg, gsendresp,
  28. #ifdef PROTA
  29.         'a', agetpkt, asendpkt, aopenpk, aclosepk, afilepkt, aeofpkt, ardmsg,  awrmsg, asendresp,
  30. #endif
  31. /*
  32.         'k', kgetpkt, ksendpkt, kopenpk, kclosepk,
  33.         'r', rgetpkt, rsendpkt, ropenpk, rclosepk,
  34.         't', tgetpkt, tsendpkt, topenpk, tclosepk,
  35. */
  36.          '0'};
  37.  
  38. #define EOTMSG "\004\r\004\r"
  39.  
  40. procref         getpkt, sendpkt, openpk, closepk, filepkt, eofpkt, getmsg, sendmsg, sendresp;
  41.  
  42. #ifdef THINK_C
  43. int checkcron(void);
  44. #endif
  45.  
  46. #include "dcpsys.proto.h"
  47.  
  48. void hangup()
  49. {
  50.     if ( useHardwareFlowControl ) {
  51.         printmsg(2, "HAYES attention/hangup");
  52.         sendexpect("\\d\\p+++\\c","OK",5);
  53.         sendexpect("\\pAAATH","OK",2);
  54.     }
  55. }
  56.  
  57. void zzz(int nsecs)
  58. {
  59. #ifdef MULTIFINDER
  60.     long int endTime = TickCount() + nsecs * 60L;
  61.     while (TickCount() < endTime) {
  62.       if (Check_Events(10)) 
  63.         if (Main_State == Abort_Program) {
  64.             hangup();
  65.             (*currentConnection->Close)(TRUE);
  66.             exit(-1);
  67.         }
  68.       }
  69. #else
  70.     sleep(nsecs);
  71. #endif
  72. }
  73.  
  74.  
  75. /**/
  76.  
  77. /***************************************************************/
  78. /***            Sub Systems             */
  79. /*
  80. **
  81. **getsystem
  82. ** Process an "systems" file entry (like L.sys)
  83. */
  84. getsystem(char *rmthost)
  85. {
  86.     int    i,blankline;
  87.     char tmpline[BUFSIZ],*p;
  88.     
  89.     *sysline = 0;    /* empty out sysline */
  90.     while(fgets( tmpline, BUFSIZ, fsys) != (char *)NULL) {
  91.         for(blankline=TRUE, p=tmpline; *p; p++) {
  92.             if(!isspace(*p)) {
  93.                 blankline = FALSE;
  94.                 break;
  95.             }
  96.         }
  97.         if(blankline)            /* skip blank lines */
  98.             continue;
  99.         if(*p == '#')            /* skip comment lines */
  100.             continue;
  101.         
  102.         if(tmpline[strlen(tmpline)-2] == '\\') {
  103.             tmpline[strlen(tmpline)-2] = ' ';    /* got continuation line */
  104.             tmpline[strlen(tmpline)-1] = (char)NULL;    /* throw away the newline char */
  105.             strcat(sysline, tmpline);
  106.             continue;
  107.         }
  108.         else {
  109.             strcat(sysline, tmpline);        /* not continued, take it and move on */
  110.             break;
  111.         }
  112.     }
  113.     
  114.     if(strlen(sysline) == 0)
  115.         return('A');
  116.         
  117.     for (i = 0; i < NFLDS; i++) flds[i] = NULL;
  118.  
  119.     printmsg( 2, "%s", sysline );
  120.  
  121.     kflds = getargs( sysline, flds );
  122.     
  123.     /* if this system isn't the one we're calling or we're not calling
  124.        a special set of systems then return 'I' and try the next one */
  125.     if ( strcmp(rmthost, flds[FLD_REMOTE] ) != SAME &&
  126.          strcmp(rmthost, "list") != SAME &&
  127.          strcmp(rmthost, "any")  != SAME &&
  128.          strcmp(rmthost, "all")  != SAME &&
  129.          strcmp(rmthost, "cron") != SAME &&
  130.          strcmp(rmthost, "need") != SAME &&
  131.          strcmp(rmthost, "auto") != SAME)
  132.         return( 'I' );
  133.     
  134.     if (strcmp(rmthost, "INCOMING") == SAME && remote == MASTER) {
  135.         return ('I');
  136.     }
  137.         
  138.     strcpy( rmtname, flds[FLD_REMOTE] );
  139.     cctime = flds[FLD_CCTIME];
  140.     strcpy( device, flds[FLD_DEVICE] );
  141.  
  142.     /* strcpy( type, flds[FLD_TYPE] ); */
  143.     strcpy( speed, flds[FLD_SPEED] );
  144.     strcpy( proto, flds[FLD_PROTO] );
  145.     strcpy( phone, flds[FLD_PHONE] );
  146.  
  147.     if (debuglevel > 3)
  148.         for (i = FLD_EXPECT; i < kflds; i += 2)
  149.             fprintf( stderr, "expect[%02d]:\t%s\nsend  [%02d]:\t%s\n",
  150.                 i, flds[i], i+1, flds[i+1] );
  151.  
  152.     printmsg( 2, "rmt= %s ctm= %s", rmtname, flds[FLD_CCTIME] );
  153.     printmsg( 2, "dev= %s ", device );
  154.     printmsg( 2, "spd= %s pro= %s", speed, proto );
  155.     printmsg( 2, "phn= %s ", phone );
  156.     
  157.     if (fw != (FILE *)NULL) {
  158.         fclose(fw);
  159.         fw = (FILE *)NULL;
  160.     }
  161.     
  162.     if (strcmp(rmthost, "list") == SAME) {
  163.         return 'I';
  164.     }
  165.     
  166.     /* first make sure it's ok to call the system at this time, if so,
  167.        then make sure it's a system we are supposed to call */
  168.     strcpy(callcause, "user request");
  169.     if ( ((strcmp(rmthost, "all")   == SAME && strcmp(rmtname, "INCOMING") != SAME) ||
  170.           (strcmp(rmthost, rmtname) == SAME) ||
  171.            ((strcmp(rmthost, "any") == SAME) && scandir() == 'S') ||
  172.            ((strcmp(rmthost, "cron") == SAME) && checkcron() == 'S') ||
  173.            ((strcmp(rmthost, "need") == SAME || strcmp(rmthost, "auto") == SAME) && (scandir() == 'S' || checkcron() == 'S')))
  174.        )
  175.     {
  176.         if (fw != (FILE *)NULL) {
  177.             fclose(fw);
  178.             fw = (FILE *)NULL;
  179.         }
  180.         if ( checktime(cctime) ) {
  181.             return('S');      /* startup this system */
  182.         } else {
  183.             return('T');      /* wrong time */
  184.         }
  185.     } else {
  186.         if (fw != (FILE *)NULL) {
  187.             fclose(fw);
  188.             fw = (FILE *)NULL;
  189.         }
  190.         return('I');    /* don't call this system, try the next one */
  191.     }
  192. }
  193.  
  194.  
  195. /**/
  196. /*
  197. **
  198. **checkname
  199. ** Do we know the guy ?
  200. */
  201. checkname(char name[])
  202. {
  203.     FILE *ff;
  204.     char line[BUFSIZ], tmp[20]; /* can change to 8 if %8s works */
  205.  
  206.     if ( ( ff = FOPEN( s_systems, "r", 't' )) == (FILE *)NULL ) {
  207.         printmsg(0, "Error %d, can't open %s file!", errno, s_systems);
  208.         return( FAILED );
  209.     }
  210.  
  211.     while ( fgets( line, BUFSIZ, ff ) != (char *)NULL ){
  212.         sscanf( line, "%8s ", tmp );
  213.         printmsg( 3, "rmt= %s sys= %s", name, tmp );
  214.         if (strncmp(line, "ANONYMOUS", 9) == 0 || strncmp( tmp, name, 7 ) == 0 ) {
  215.             fclose( ff );
  216.             return ( OK ); /*OK I like you */
  217.         }
  218.     }
  219.     fclose( ff );
  220.     return( FAILED ); /* Who are you ? */
  221.  
  222. }
  223.  
  224.  
  225. void Schedule_To_List(char *Schedule, datalist Schedule_List, int Min, int Max);
  226. void Compute_Next_Call_Time(status_record Last, schedule_record Schedule, struct tm *Next );
  227. int Time_Less_Than_Or_Equal(struct tm *Left, struct tm *Right);
  228.  
  229. int Time_Less_Than_Or_Equal(struct tm *Left, struct tm *Right)
  230. {
  231.     /* check the months first */
  232.     if (Left->tm_mon < Right->tm_mon) return TRUE;
  233.     if (Left->tm_mon > Right->tm_mon) return FALSE;
  234.     
  235.     /* months are the same, check the day */
  236.     if (Left->tm_mday < Right->tm_mday) return TRUE;
  237.     if (Left->tm_mday > Right->tm_mday) return FALSE;
  238.     
  239.     /* days are the same, check the hour */
  240.     if (Left->tm_hour < Right->tm_hour) return TRUE;
  241.     if (Left->tm_hour > Right->tm_hour) return FALSE;
  242.     
  243.     /* hours are the same, check the minute */
  244.     if (Left->tm_min > Right->tm_min) return FALSE;
  245.     return TRUE;
  246. }
  247.  
  248.  
  249. void Schedule_To_List(char *Schedule, datalist Schedule_List, int Min, int Max)
  250. {
  251.     /* take a character string describing this schedule entry and
  252.        convert it to a list of times that are acceptable, see format
  253.        and examples below.
  254.        
  255.        Format (no spaces allowed in actual string):
  256.            number :== digit{digit}
  257.            range  :== number '-' number
  258.            item   :== range | number    
  259.            entry  :==  '*' | item {, item}
  260.        Example:
  261.            "*"  "1-5,8"  "1,3,5,7,9,11" "0-7,17-23"
  262.     */
  263.     int i,k,m;
  264.     char *p;
  265.     
  266.     if (strcmp(Schedule,"*")==SAME) {
  267.         for (i=0, k=Min; k<=Max; k++, i++) 
  268.             Schedule_List[i] = k;
  269.         return; 
  270.     }
  271.     
  272.     /* scan for list entries */
  273.     p = Schedule;
  274.     i = 0;
  275.     while (*p) {
  276.         if (isdigit(*p)) {
  277.             /* got a number */
  278.             sscanf(p, "%d", &k);        /* got a list entry */
  279.             Schedule_List[i++] = k;        /* put it in the list */
  280.             while (isdigit(*p)) p++;    /* skip past number */
  281.             
  282.         } else if (*p == ',') {
  283.             /* got a comma */
  284.             p++;        /* skip the comma */
  285.         } else if (*p == '-') {
  286.             /* got a dash, must be a range */
  287.             p++;        /* skip the dash */
  288.             sscanf(p, "%d", &m);        /* get the end of the range */
  289.             while (k <= m) {            /* put entries for the range in the list */
  290.                 Schedule_List[i++] = k++;
  291.             }
  292.             while (isdigit(*p)) p++;    /* skip past number */
  293.         } else {
  294.             p++;
  295.         }
  296.         Schedule_List[i] = -1;
  297.     }
  298. }    
  299.  
  300. int Validate_Value(int Value, datalist Valid_List);
  301. int Validate_Value(int Value, datalist Valid_List)
  302. {
  303.     int i = 0;
  304.  
  305.     while ((Valid_List[i] < Value) && (Valid_List[i] >= 0))
  306.         i++;
  307.     
  308.     if (Valid_List[i] < 0) {
  309.         /* didn't find the value, use the first entry */
  310.         return Valid_List[0];
  311.     } else {
  312.         /* found the value or the next larger one, it's ok to use it */
  313.         return Valid_List[i];
  314.     }
  315. }
  316.  
  317. int Add_Field(int Last, int *Next, datalist Valid_List, int *Carry);
  318. int Add_Field(int Last, int *Next, datalist Valid_List, int *Carry)
  319. {
  320.     *Next = Last + *Carry;        /* add the carry in (may be 0) */
  321.     
  322.     /* make sure the time is a valid value for this field */
  323.     *Next = Validate_Value(*Next, Valid_List);
  324.     
  325.     /* if the value is lower than the last time, set the carry flag (overflow) */
  326.     if (*Next < Last) {
  327.         *Carry = 1;        /* to make it less we had to wrap around, causing a carry */
  328.     } else if (*Next == Last && *Carry == 1) {
  329.         /* we had a carry but it didn't increment; it must have wrapped all the
  330.            way back around to where we started, this should cause a carry */
  331.         *Carry = 1;
  332.     } else {
  333.         *Carry = 0;
  334.     }
  335.         
  336.     /* if the value is different from last time, then return 1 to indicate it
  337.        must reset the less significant fields to their minimum values */
  338.     if (*Next != Last || *Carry == 1) return 1;
  339.     return 0;
  340. }
  341.  
  342. int Day_Of_Week(int Month, int Day, int Year);
  343. int Day_Of_Week(int Month, int Day, int Year)        /* 1904-2040 */
  344. /* Returns Day_Of_Week where 1=Mon...5=Fri, 6=Sat, 7=Sun */
  345. {
  346.     DateTimeRec Tmp_DTR;
  347.     long Secs;
  348.     
  349.     Tmp_DTR.year   = (Year >= 80 ? 1900+Year : 2000+Year);
  350.     Tmp_DTR.month  = Month;
  351.     Tmp_DTR.day    = Day;
  352.     Tmp_DTR.hour   = 0;
  353.     Tmp_DTR.minute = 0;
  354.     Tmp_DTR.second = 0;
  355.     Tmp_DTR.dayOfWeek = 1;
  356.     
  357.     Date2Secs(&Tmp_DTR, &Secs);    /* day of week not needed */
  358.     Secs2Date(Secs, &Tmp_DTR);    /* day of week return in conversion */
  359.     
  360.     if (Tmp_DTR.dayOfWeek == 1) 
  361.         return 7;  /* Sunday */
  362.     else
  363.         return Tmp_DTR.dayOfWeek - 1;
  364. }
  365.  
  366. void Compute_Next_Call_Time(status_record Last, schedule_record Schedule, struct tm *Next)
  367. {
  368.     schedule_list_record Valid_Lists;    
  369.     int carry;                /* start with a carry to increment to next time value */
  370.     int field = 0;
  371.     struct tm Last_Time;
  372.     
  373.     Last_Time = *localtime(&Last.time_secs);
  374.     Last_Time.tm_mon++;        /* make months 1 based */
  375.     *Next = Last_Time;
  376.     
  377.     Schedule_To_List(Schedule.min,     Valid_Lists.min,     0, 59);
  378.     Schedule_To_List(Schedule.hour,    Valid_Lists.hour,    0, 23);
  379.     Schedule_To_List(Schedule.day,     Valid_Lists.day,     1, 31);
  380.     Schedule_To_List(Schedule.month,   Valid_Lists.month,   1, 12);
  381.     Schedule_To_List(Schedule.weekday, Valid_Lists.weekday, 1, 7);
  382.  
  383.     /* find the next larger valid time for the field */
  384.     carry = 1;
  385.     if (Add_Field(Last_Time.tm_min, &Next->tm_min, Valid_Lists.min, &carry)) {
  386.         /* field was set backwards, we must update the less significant fields
  387.             to their minimum values */
  388.         /* there are no less significant fields (we don't use seconds at all) */
  389.     }
  390.  
  391.     if (Add_Field(Last_Time.tm_hour, &Next->tm_hour, Valid_Lists.hour, &carry)) {
  392.         /* field was set backwards, we must update the less significant fields to their
  393.            minimum values */
  394.         Next->tm_min = Valid_Lists.min[0];
  395.     }
  396.  
  397.   try_the_next_day:
  398.       
  399.     if (Add_Field(Last_Time.tm_mday, &Next->tm_mday, Valid_Lists.day, &carry)) {
  400.         /* field was set backwards, we must update the less significant fields to their
  401.            minimum values */
  402.         Next->tm_hour = Valid_Lists.hour[0];
  403.         Next->tm_min  = Valid_Lists.min[0];
  404.     }
  405.     
  406.     if (Add_Field(Last_Time.tm_mon, &Next->tm_mon, Valid_Lists.month, &carry)) {
  407.         /* field was set backwards, we must update the less significant fields to their
  408.            minimum values */
  409.         Next->tm_mday = Valid_Lists.day[0];
  410.         Next->tm_hour = Valid_Lists.hour[0];
  411.         Next->tm_min  = Valid_Lists.min[0];
  412.     }
  413.     
  414.     /* see if day of week of the computed next call time is a valid 
  415.        day of the week given the days that are allowed */
  416.     Next->tm_wday = Day_Of_Week(Next->tm_mon, Next->tm_mday, Next->tm_year);
  417.     if (Validate_Value(Next->tm_wday, Valid_Lists.weekday) != Next->tm_wday) {
  418.       /* weekday doesn't match list of valid weekdays, so try the next 
  419.          possible day that we could call and see if it falls on the right
  420.          weekday.  Keep doing this until we find a valid day that is on a valid
  421.          weekday. */
  422.       Last_Time = *Next;
  423.       carry = 1;        /* so day will get incremented */
  424.       goto try_the_next_day;
  425.     }
  426.     
  427.     Next->tm_mon--;        /* make months 0 based again */
  428.     
  429.     /*** weekday restrictions are not being handled yet ***/
  430. }
  431.  
  432. /* get status information from file.  Returns TRUE on success, FALSE on failure. */
  433.  
  434. int GetStatus(void)
  435. {
  436.     FILE *fp;
  437.     char line[BUFSIZ];
  438.     char stfile[80];            /* constructed status file name */
  439.     int n;
  440.     if (strcmp(Last.name, rmtname) == SAME) {
  441.         return TRUE;
  442.     }
  443.     sprintf(stfile, "%s%s", s_statfile, rmtname);
  444.     
  445.     /* if there is no status file, assume it has never been called */
  446.     if ((fp=FOPEN(stfile, "r", 't')) == (FILE *)NULL) {
  447.         printmsg( 1, "No status file for system %s", rmtname );
  448.         goto fakeit;
  449.     }
  450.     
  451.     n = 0;
  452.     if (fgets(line, BUFSIZ, fp) != (char *)NULL) {
  453.         /* got status line into buffer */
  454.         /* line format:
  455.                 ctime system status [failures]
  456.            ctime is epoch time in seconds from time function
  457.            status may be OK or FAILED */
  458.         Last.failures = 0;
  459.         n = sscanf(line, "%ld %s %s %d",
  460.                    &Last.time_secs, Last.name, Last.status, &Last.failures);
  461.         if (n < 3 ||
  462.             strcmp(rmtname, Last.name) != SAME) n = 0;
  463.     }
  464.     fclose(fp);
  465.     if (n == 0) {
  466.         printmsg( 1, "Unable to read status line" );
  467. fakeit: strcpy(Last.name, rmtname);
  468.         strcpy(Last.status, "OK");
  469.         Last.failures = 0;
  470.         Last.time_secs = 0;
  471.         return FALSE;
  472.     }
  473.     return TRUE;
  474. }
  475.  
  476. /**/
  477. /*
  478. **
  479. ** checkcron()
  480. ** check if we should call a system at this time.
  481. **
  482. ** returns 'S' if system needs be called
  483. ** returns 'I' if system doesn't need to be called
  484. **
  485. ** "need" is based on schedule file not by what is spooled, use "any"
  486. ** if you want to send spooled data out.
  487. **
  488. ** system needs to be called if any of the following conditions are met:
  489. **
  490. ** (1) status file "ST.<system>" doesn't exist
  491. ** (2) status file indicates last call failed and the elapsed time since
  492. **     the failure exceeds the retrytime entry in the schedule file.
  493. ** (3) status file indicates last call was ok and according to the
  494. **     schedule file there should have been a call during the time when
  495. **     the last called occurred and the current time.
  496. */
  497. int checkcron(void)
  498. {
  499.     FILE *fp;
  500.     char line[BUFSIZ];
  501.     char stfile[80];            /* constructed status file name */
  502.     int n;
  503.     time_t Cur_Time_Secs, Retry_Expiration;
  504.     
  505.     schedule_record Schedule;
  506.     struct tm Next, Current_Time;
  507.     
  508.     /* got a real problem if schedule file is missing */
  509.     if ((fp=FOPEN(s_schedule, "r", 't')) == (FILE *)NULL) {
  510.         printmsg( 1, "Schedule file '%s' missing", s_schedule );
  511.         return('I');        /* no schedule, so don't call anyone */
  512.     }
  513.     
  514.     n = 0;
  515.     while (n==0 && fgets(line, BUFSIZ, fp) != (char *)NULL){
  516.         /* line format:
  517.             min hour day month weekday system [retrytime] */
  518.         if (line[0] != '#') {
  519.             Schedule.retrytime = 1;
  520.             n = sscanf(line, "%s %s %s %s %s %s %d",
  521.                        Schedule.min, Schedule.hour, Schedule.day,
  522.                        Schedule.month, Schedule.weekday, Schedule.name,
  523.                        &Schedule.retrytime);
  524.             if (n < 6 ||
  525.                 strcmp(rmtname, Schedule.name) != SAME) n = 0;
  526.         }
  527.     }
  528.     fclose(fp);
  529.     if (n == 0) {
  530.         printmsg( 1, "System %s not in schedule", rmtname );
  531.         return ('I');    /* didn't find the system in schedule, don't call it */
  532.     }
  533.     
  534.     /* we have the schedule now, now we need the current status */
  535.     if (!GetStatus()) {
  536.         strcpy(callcause, "scheduled call");
  537.         return('S');
  538.     }
  539.     
  540.     if (strcmp(Last.status,"OK") != SAME  && Schedule.retrytime) {
  541.         /* no retries if retrytime is 0, just the scheduled calls */
  542.         
  543.         /* last call failed, see if failed during current run.  If so,
  544.            try again (additional phone number) */
  545.         if (Last.time_secs >= runStartSecs) {
  546.             return ('S');
  547.         }
  548.         /* Failed during previous run.  See if the retry time has expired */
  549.         Retry_Expiration = Last.time_secs + Schedule.retrytime * 60;
  550.         time(&Cur_Time_Secs);
  551.         if (Cur_Time_Secs >= Retry_Expiration) {
  552.             printmsg( 1, "RETRY time for %s", rmtname );
  553.             strcpy(callcause, "retry of scheduled call");
  554.             return ('S');        /* retry time past, call system again */
  555.         } else {
  556.             printmsg( 1, "Retry time for %s not reached yet", rmtname );
  557.             return ('I');        /* not time yet, don't call system */
  558.         }
  559.     }
  560.     
  561.     /* last call was successful, see if it's time to call this system again */
  562.     Compute_Next_Call_Time( Last,        /* time of last successful call */
  563.                             Schedule,    /* time schedule pattern */
  564.                             &Next);        /* next time it should be called */
  565.                             
  566.     time(&Cur_Time_Secs);
  567.     Current_Time = *localtime(&Cur_Time_Secs);
  568.     
  569.     if (Time_Less_Than_Or_Equal(&Next, &Current_Time) == TRUE) {
  570.         /* the Next time has past (it's less than the current time) so that means
  571.            we should call this system */
  572.         strcpy(callcause, "scheduled call");
  573.         return ('S');        /* call this system */
  574.     } else {
  575.         printmsg( 1, "Scheduled call time for %s not reached yet",
  576.                      rmtname );
  577.         return ('I');        /* not time to call yet, don't call system */
  578.     }
  579. }
  580.  
  581.  
  582. void Update_Status(int New_Status)
  583. {
  584.     /* rewrite status file with latest results */
  585.     char stfile[80];
  586.     time_t cur_time;
  587.     FILE *fp;
  588.     
  589.     sprintf(stfile, "%s%s", s_statfile, rmtname);
  590.     
  591.     if ((fp=FOPEN(stfile, "w", 't')) == (FILE *)NULL) return;
  592.     
  593.     time(&cur_time);
  594.     if (New_Status == OK) {
  595.         fprintf(fp, "%ld %s %s\r",
  596.                 cur_time, rmtname, "OK");
  597.         Last.time_secs = cur_time;
  598.     } else {
  599.         fprintf(fp, "%ld %s %s %d\r",
  600.             cur_time, rmtname, "FAILED", failureCount);
  601.     }
  602.     fclose(fp);
  603. }
  604.  
  605. /**/
  606. /*
  607. **
  608. **checktime
  609. ** check if we may make a call at this time
  610. **
  611. ** acceptable formats:  "Any", "Evening", "Night", "hhmm-hhmm"
  612. ** hhmm-hhmm may be a inclusive range, ie: 0000-0600,
  613. ** or it can be an range that specifies morning and evening hours,
  614. ** ie: 1700-0700 (means 0000-0700 and 1700-2359)
  615. **
  616. ** Evening includes the standard AT&T long distance hours from 1700 to
  617. ** 0800 plus all day Saturday and all day Sunday except evening hours.
  618. **
  619. ** Time may also include a retry interval (e.g. "evening;10") to specify
  620. ** the minimum retry interval.  If a retry interval is specified, it will
  621. ** be used precisely as given.  If no retry interval is specified, a
  622. ** HoneyDanBer-style exponential backoff algorithm is used... the retry
  623. ** time will be 5 minutes after the first failed attempt, 10 minutes after
  624. ** the second, 20 after the third, and so forth... up to a maximum backoff
  625. ** of 23 hours.
  626. **
  627. ** The retry interval is applied during calls to "any", "all", "cron", and
  628. ** "auto".  It is _not_ applied during a call directed to a specific site...
  629. ** this allows the user to force a call without having to manually trash
  630. ** the ST.sitename file.
  631. */
  632. checktime(char xtime[])
  633. {
  634.     struct tm    *t;
  635.     int Cur_Time = 0;
  636.     int Left,Right;
  637.     int Is_OK = FALSE;
  638.     char mytime[256],retrystring[256];
  639.     char line[BUFSIZ];
  640.     long int backoff;
  641.     char *p;
  642.     int i, n;
  643.     char stfile[80];            /* constructed status file name */
  644.     time_t Retry_Expiration;
  645.     FILE *fp;
  646.     
  647.     if ((p = strchr(xtime, ';')) == NULL) {
  648.         strcpy(mytime, xtime);
  649.         backoff = -1;
  650.     } else {
  651.         strncpy(mytime, xtime, p - xtime);
  652.         mytime[p-xtime] = '\0';
  653.         if (sscanf(p+1, "%ld", &backoff) != 1 || backoff <= 0 || backoff > 60*24*7) {
  654.             backoff = -1;
  655.         }
  656.     }
  657.     time(&theTime);
  658.     t = localtime(&theTime);
  659.     Cur_Time = t->tm_hour*100 + t->tm_min;
  660.     
  661.     for (p=mytime; *p; p++) *p = tolower(*p);    /* convert to lower */
  662.     
  663.     printmsg( 2, "curtime= %d mytime= %s", Cur_Time, mytime );
  664.  
  665.     if (strcmp(mytime,"any")==SAME) {
  666.         /* any time allowed */
  667.         Is_OK = TRUE;
  668.         
  669.     } else if (isdigit(*mytime) &&
  670.                (sscanf(mytime,"%d-%d",&Left,&Right) == 2)) {
  671.         /* time range */
  672.         if (Left <= Right) {
  673.             /* inclusive range, ie: 1700-2300 */
  674.             if (Cur_Time >= Left && Cur_Time < Right) Is_OK = TRUE;
  675.         } else {
  676.             /* complex range, ie: 2300-0800 */
  677.             /* ranges are: 0000-Right + Left-2359 */
  678.             if (Cur_Time < Right || Cur_Time >= Left) Is_OK = TRUE;
  679.         }
  680.         
  681.     } else if (strcmp(mytime,"evening")==SAME) {
  682.         /* evening time period (includes night rates, basicall anytime
  683.            except weekday daytime rates) */
  684.         if (Cur_Time <  800  ||        /* early morning is night rate */
  685.             Cur_Time >= 1700 ||        /* evening is evening or night rate */
  686.             t->tm_wday == 0  ||     /* sunday is all evening or night */
  687.             t->tm_wday == 6)         /* saturday is night rates */
  688.           Is_OK = TRUE;
  689.         
  690.     } else if (strcmp(mytime,"night")==SAME) {
  691.         /* night rate time period */
  692.         if (Cur_Time <  800 ||        /* early morning is night rates */
  693.             Cur_Time >= 2300 ||        /* late night rates */
  694.             t->tm_wday == 6  ||     /* saturday is night rates */
  695.                                     /* sunday daytime is night rates, evening
  696.                                        night rates already handled */
  697.             (t->tm_wday == 0 &&    Cur_Time < 1700) ||
  698.                                     /* friday evening is night rates */
  699.             (t->tm_wday == 5 && Cur_Time >= 1700))
  700.           Is_OK = TRUE;
  701.         
  702.     } else if (strcmp(mytime,"never")==SAME) {
  703.         Is_OK = FALSE;
  704.         
  705.     } else {
  706.         /* didn't match known formats, flag an format error */
  707.         printmsg( 0, "bad time format in System file: %s", mytime );
  708.     }
  709.  
  710.     if (debuglevel > 0 && !Is_OK) {
  711.         printmsg( 1, "wrong time to call %s, allowed at: %s",
  712.                      rmtname, mytime);
  713.     }
  714.     if (!Is_OK) {
  715.         return FALSE;
  716.     }
  717.     
  718.     /* it's the right time of day. now we need the current status */
  719.     if (!GetStatus()) {
  720.         failureCount = 0;
  721.         return('S');
  722.     }
  723.     
  724.     failureCount = Last.failures;
  725.     
  726.     if (strcmp(Last.status,"OK") == SAME || strcmp(rmtname, Rmtname) == SAME) {
  727.         return TRUE;
  728.     }
  729.  
  730.     /* Failed during previous run.  See if the retry time has expired */
  731.     if (backoff == -1) { /* HDB-style exponential backoff */
  732.         if (failureCount == 0) {
  733.             backoff = 5;
  734.         } else if (failureCount >= 10) {
  735.             backoff = 23 * 60;
  736.         } else {
  737.             backoff = 5 << (failureCount - 1);
  738.         }
  739.     }
  740.     Retry_Expiration = Last.time_secs + backoff * 60;
  741.     if (theTime >= Retry_Expiration) {
  742.         return (TRUE);        /* retry time past, call system again */
  743.     } else {
  744.         printmsg( 1, "Retry time for %s not reached yet, %ld minutes to go", rmtname,
  745.                     (Retry_Expiration - theTime + 59) / 60 );
  746.         return (FALSE);        /* not time yet, don't call system */
  747.     }
  748. }
  749.  
  750. /**/
  751. /*
  752. **
  753. **      delay
  754. **
  755. */
  756. /*ddelay(dtime)
  757. int    dtime;
  758. {
  759.     int    i, j;
  760.     for (i = 0; i < dtime; i++) {
  761.     }
  762. }
  763.  
  764. */
  765.  
  766. paceit (void)
  767. {
  768.     EventRecord    theEvent;
  769.     long timea;
  770.  
  771.     timea = Ticks+4; /* 1/15 - 1/20 second spin */
  772.  
  773.     while (Ticks < timea) {
  774. #ifdef MULTIFINDER
  775.         Check_Events(MF_DELAY);
  776. #else
  777.         (void) EventAvail(everyEvent, &theEvent);
  778.         SystemTask();
  779. #endif
  780.     }
  781. }
  782.  
  783.  
  784. /**/
  785. /*
  786. **
  787. **sysend
  788. ** end UUCP session negotiation
  789. */
  790. sysend(void)
  791. {
  792.     char    msg[80];
  793.  
  794.     msg[1] = '\0';
  795.     msgtime = 5; /* dplatt, don't hang around for so long... */
  796. /*     msgtime = 2 * MSGTIME; */
  797.     wmsg("OOOOOO", 2);
  798.     if (rmsg(msg, 2) == -1)
  799.             goto hang;
  800.     /*}*/
  801. hang:
  802.     wmsg("OOOOOO", 2);
  803.     
  804.     closeline();
  805.     printmsg( 0, "Over and out");
  806.     if ( remote == MASTER )
  807.         return('I');
  808.     return('A');
  809. }
  810.  
  811.  
  812. /*
  813. **
  814. **wmsg
  815. ** write a ^P type msg to the remote uucp
  816. */
  817. wmsg(char msg[], int syn)
  818. {
  819.     int    len;
  820.     len = strlen(msg);
  821.     if (syn == 2)
  822.         swrite("\0\020", 2);
  823.     swrite(msg, len);
  824.     if (syn == 2)
  825.         swrite("\0", 1);
  826. }
  827.  
  828.  
  829. /*
  830. **
  831. **rmsg
  832. ** read a ^P msg from UUCP
  833. */
  834. rmsg(char msg[], int syn)
  835. {
  836.     int    ii;
  837.     char    c, cc[5];
  838.     /* *msg0;*/
  839.     /*msg0 = msg;*/
  840.     
  841.     c = 'a';
  842.     if (syn == 2) {
  843.         while ((c & 0x7f) != '\020') {
  844.             if (sread(cc, 1, msgtime) < 1)
  845.                 return(-1);
  846.             c = cc[0]; /* Dont ask. MSC needs more than a byte to breathe */
  847.             /*        printf("Hello im in rmsg c=%x\n",c); */
  848.         }
  849.     }
  850.     for (ii = 0; ii < 132 && c ; ii++) {
  851.         if (sread(cc, 1, msgtime) < 1)
  852.             return(-1);
  853.         c = cc[0] & 0x7f;
  854.         if (c == '\r' || c == '\n')
  855.             c = '\0';
  856.         msg[ii] = c;
  857.         /*if(c == '\020') msg = msg0; */
  858.     }
  859.  
  860.     return(strlen(msg));
  861. }
  862.  
  863. void cleanmsg(char *msg)
  864. {
  865.     char c;
  866.     while ((c = *msg)) {
  867.         if (!isprint(c)) {
  868.             c = '?';
  869.         }
  870.         *msg++ = c;
  871.     }
  872. }
  873.  
  874.  
  875.  
  876. /**/
  877. /*
  878. **
  879. **
  880. **startup
  881. **
  882. **
  883. */
  884. startup(void)
  885. {
  886.     char    msg[255], tmp1[255], tmp2[255];
  887.     memset((void *) &remote_stats, 0, (size_t) sizeof remote_stats);
  888.     if ( remote == MASTER ) {
  889.         msgtime = 2 * MSGTIME;
  890.         if (rmsg(msg, 2) == -1) {
  891.             printmsg( 0, "1st msg (\"Shere\") never arrived" );
  892.             return('X');
  893.         }
  894.         cleanmsg(msg);
  895.         if (strncmp(msg, "Shere", 5) != 0) {
  896.             printmsg(0, "1st msg not Shere: %s", msg);
  897.             return('X');
  898.         }
  899.         printmsg( 2, "1st msg: %s", msg );
  900.         if (msg[5] == '=' && strncmp(&msg[6], rmtname, 7)) {
  901.             printmsg( 0, "Not who we expected it to be: %s", msg );
  902.             return('Y');
  903.         }
  904.  
  905.  
  906.         /*sprintf(msg, "S%.7s -Q0 -x%d", nodename, debuglevel);*/  /* -Q0 -x16 remote debuglevel set */
  907.  
  908.         sprintf(msg, "S%s", shortname);
  909.  
  910.         wmsg(msg, 2);
  911.         if (rmsg(msg, 2) == -1) {
  912.             printmsg( 0, "2nd msg (responce to \"S%s\") never arrived", shortname );
  913.             return('X');
  914.         }
  915.         cleanmsg(msg);
  916.         printmsg( 2, "2nd msg: %s", msg );
  917.         if (strncmp(msg, "RLCK", 4) == 0) {
  918.             printmsg(0, "%s says it has a lock for you", rmtname);
  919.             return ('Y');
  920.         } else if (strncmp(msg, "RCB", 3) == 0) {
  921.             printmsg(0, "%s says it will call you back", rmtname);
  922.             return ('Y');
  923.         } else if (strncmp(msg, "RLOGIN", 6) == 0) {
  924.             printmsg(0, "%s says you are using an incorrect login name", rmtname);
  925.             return ('X');
  926.         } else  if (strncmp(&msg[1], "OK", 2)) {
  927.             printmsg( 2, "2nd msg not OK" );
  928.             printmsg( 0, "2nd msg: %s", msg);
  929.             return('X');
  930.         }
  931.         if (rmsg(msg, 2) == -1) {
  932.             printmsg( 2, "3rd msg (protocol list) never arrived" );
  933.             return('X');
  934.         }
  935.         cleanmsg(msg);
  936.         printmsg( 2, "3rd msg = %s", msg );
  937.         if (msg[0] != 'P' || index(&msg[1], proto[0]) == (char *)NULL) {
  938.             printmsg(0, "Protocol disagreement");
  939.             wmsg("UN", 2);
  940.             return('X');
  941.         }
  942.         sprintf(msg, "U%c", proto[0]);
  943.         wmsg(msg, 2);
  944.         setproto(proto[0]);
  945.         printmsg( 0, "OK Startup '%c'", proto[0]);
  946.         return('D');
  947.     } else {
  948.         msgtime = 2 * MSGTIME;
  949.         sprintf(msg, "Shere=%s", shortname);
  950.         wmsg(msg, 2);
  951.         if (rmsg(msg, 2) == -1)
  952.             return('Y');
  953.         cleanmsg(msg);
  954.         sscanf(&msg[1], "%s %s %s", rmtname, tmp1, tmp2);
  955.         sscanf(tmp2, "-x%d", &debuglevel);
  956.         printmsg( 1, "debuglevel level = %d", debuglevel );
  957.         printmsg( 2, "1st msg from remote = %s", msg );
  958.         if (checkname(rmtname)) {
  959.             wmsg("RYou are unknown to me", 2);
  960.             printmsg(0, "Rejected a connection from %s (unknown)", rmtname);
  961.             zzz(1);
  962.             return('Y');
  963.         }
  964.         wmsg("ROK", 2);
  965.         sprintf(msg, "P%s", PROTOS);
  966.         wmsg(msg, 2);
  967.         if (rmsg(msg, 2) == -1) {
  968.             printmsg(0, "Never got Use-protocol message from %s", rmtname);
  969.             return('Y');
  970.         }
  971.         if (msg[0] != 'U' || index(PROTOS, msg[1]) == (char *)NULL ) {
  972.             printmsg(0, "Protocol disagreement with %s", rmtname);
  973.             return('Y');
  974.         }
  975.         proto[0] = msg[1];
  976.         setproto(proto[0]);
  977.         printmsg( 0, "Call from %s connected", rmtname);
  978.         return('R');
  979.     }
  980. }
  981.  
  982.  
  983. /******* set the protocol **********/
  984. setproto(char pr)
  985. {
  986.     int    i;
  987.     Proto * tproto;
  988.     for (tproto = Protolst; tproto->type != '\0' && pr != tproto->type; tproto++) {
  989.         printmsg( 3, "setproto: %c %c", pr, tproto->type );
  990.     }
  991.     if (tproto->type == '\0') {
  992.         printmsg( 0, "setproto:You said I had it but I cant find it" );
  993.         hangup();
  994.         (*currentConnection->Close)(TRUE);
  995.         exit(1);
  996.     }
  997.     getpkt = tproto->a;
  998.     sendpkt = tproto->b;
  999.     openpk = tproto->c;
  1000.     closepk = tproto->d;
  1001.     filepkt = tproto->e;
  1002.     eofpkt = tproto->f;
  1003.     getmsg = tproto->g;
  1004.     sendmsg = tproto->h;
  1005.     sendresp = tproto->i;
  1006. }
  1007.  
  1008.  
  1009.  
  1010. /**/
  1011. int prefix(char *sh, char *lg)
  1012. {
  1013.     return( strncmp(sh,lg,strlen(sh)) == SAME);
  1014. }
  1015.  
  1016. int notin(char *sh, char *lg)
  1017. {
  1018.     while (*lg) {
  1019.         if (prefix(sh,lg++))
  1020.             return( FALSE );
  1021.     }
  1022.     return( TRUE );
  1023. }
  1024.  
  1025. #define MAXR 300
  1026. int
  1027. expectstr(char *str, long int timeout)
  1028. {
  1029.     static char rdvec[MAXR];
  1030.     char *rp = rdvec;
  1031.     char expectstr[MAXR];
  1032.     int kr;
  1033.     int totlen, strip, iter, i, special;
  1034.     int totReceived;
  1035.     char nextch;
  1036.     int nbreaks, breakno;
  1037.     char *breaks[10], *breakout;
  1038.     
  1039.     nbreaks = 0;
  1040.     totReceived = 0;
  1041.  
  1042.     printmsg( 1, "wanted %s", str );
  1043.  
  1044.     if ( strcmp(str, "\"\"") == SAME || strlen(str) == 0) {
  1045.         return( TRUE );
  1046.     }
  1047.     i = 0;
  1048.     totlen = 0;
  1049.     special = 0;
  1050.     while (i < strlen(str)) {
  1051.         nextch = str[i++];
  1052.         if (special) {
  1053.             switch (nextch) {
  1054.             case 's':
  1055.                 expectstr[totlen++] = ' ';
  1056.                 break;
  1057.             case 'r':
  1058.                 expectstr[totlen++] = '\r';
  1059.                 break;
  1060.             case 'n':
  1061.                 expectstr[totlen++] = '\n';
  1062.                 break;
  1063.             case 't':
  1064.                 expectstr[totlen++] = '\t';
  1065.                 break;
  1066.             default:
  1067.                 expectstr[totlen++] = nextch;
  1068.                 break;
  1069.             }
  1070.             special = 0;
  1071.         } else if (nextch == '\\') {
  1072.             special = 1;
  1073.         } else {
  1074.             expectstr[totlen++] = nextch;
  1075.         }
  1076.     }
  1077.     expectstr[totlen] = '\0';
  1078.     if (breakout = strchr(expectstr, '•')) {
  1079.         do {
  1080.             *breakout++ = '\0';
  1081.             breaks[nbreaks++] = breakout;
  1082.             breakout = strchr(breakout, '•');
  1083.         } while (breakout);
  1084.     }
  1085.     *rp = 0;
  1086.     while ( notin( expectstr,rdvec ) ) {
  1087.         printmsg(9, "Got '%s', match on '%s''", rdvec, expectstr);
  1088.         for (breakno = nbreaks-1 ; breakno >= 0; breakno--) {
  1089.             if (!notin(breaks[breakno], rdvec)) {
  1090.                 printmsg(0, breaks[breakno]);
  1091.                 return( FALSE );
  1092.             }
  1093.         }
  1094. #ifdef MULTIFINDER
  1095.         if (Main_State != Call_Systems) {
  1096.             return ( FALSE );
  1097.         }
  1098. #endif
  1099.         /* fprintf(stderr, "---------->%s<------\n", rdvec);/**/
  1100.         kr = sread(&nextch, 1, timeout);
  1101.         if (kr <= 0) {
  1102.             return( FALSE );
  1103.         }
  1104.         if (debuglevel >= 7) {
  1105.             fputc(nextch & 0177, stdout);
  1106.         }
  1107.         totReceived++;
  1108.         if (totReceived > MAXR * 10) { /* "Enough, already!" gibberish blocker */
  1109.             printmsg(2, "He seems to be babbling...");
  1110.             return (FALSE);
  1111.         }
  1112.         if ((*rp = nextch & 0177) != '\0') {
  1113.             rp++;
  1114.         }
  1115.         if (rp >= rdvec + MAXR) { /* off end, need to toss old stuff */
  1116.             strip = MAXR - totlen - 2;
  1117.             iter = strip;
  1118.             while (iter < MAXR) {
  1119.                 rdvec[iter-strip] = rdvec[iter];
  1120.                 iter++;
  1121.             }
  1122.             rp -= strip;
  1123.         }
  1124.         *rp = '\0';
  1125.     }
  1126.     return( TRUE );
  1127. }
  1128.  
  1129. int
  1130. writestr(char *s) {
  1131.     register char last;
  1132.     register char * m;
  1133.     char ctlchar;
  1134. #ifdef MULTIFINDER
  1135.     long Last_Ticks;
  1136. #endif
  1137.     int nocr, pace;
  1138.     last = '\0';
  1139.     nocr = pace = FALSE;
  1140.     while (*s) {
  1141.         if (last == '\\') {
  1142.             switch (*s) {
  1143.             case 'd':
  1144.             case 'D': /* delay */
  1145. #ifdef MULTIFINDER
  1146.                 Last_Ticks = Ticks;
  1147.                 while (Ticks-Last_Ticks < 120) 
  1148.                   if (Check_Events(30))
  1149.                     if (Main_State == Abort_Program)  {
  1150.                         hangup();
  1151.                         (*currentConnection->Close)(TRUE);
  1152.                         exit(-1);
  1153.                     }
  1154. #else
  1155.                 delay(80000);
  1156. #endif
  1157.                break;
  1158.             case 'c':
  1159.             case 'C': /* end string don't output CR */
  1160.                nocr = TRUE;
  1161.                break;
  1162.             case 'r':
  1163.             case 'R': /* carriage return */
  1164.             case 'm':
  1165.             case 'M':
  1166.                   swrite( "\r", 1 );
  1167.                   if (pace) paceit();
  1168.                    break;
  1169.             case 'n':
  1170.             case 'N':
  1171.                   swrite( "\n", 1 );
  1172.                   if (pace) paceit();
  1173.                    break;
  1174.             case 'b':
  1175.             case 'B':
  1176.                   swrite( "\b", 1 );
  1177.                   if (pace) paceit();
  1178.                    break;
  1179.             case 't':
  1180.             case 'T':
  1181.                   swrite( "\t", 1 );
  1182.                   if (pace) paceit();
  1183.                    break;
  1184.             case 's':
  1185.             case 'S':
  1186.                   swrite( " ", 1 );
  1187.                   if (pace) paceit();
  1188.                    break;
  1189.             case 'z':
  1190.             case 'Z':
  1191.                 (*currentConnection->Speed)( ++s );
  1192.                 while ( *s != '\0' && *s != '\\' )
  1193.                     s++;
  1194.                 if ( *s == '\\' )
  1195.                     s++;
  1196.                 break;
  1197. #ifdef Upgrade
  1198.             case 'p':
  1199.             case 'P':
  1200.                   if (pace = ! pace) paceit();
  1201.                 break;
  1202.             case '0':
  1203.             case '1':
  1204.             case '2':
  1205.             case '3':
  1206.             case '4':
  1207.             case '5':
  1208.             case '6':
  1209.             case '7':
  1210.             case '8':
  1211.             case '9':
  1212.                 for(systimeout = *s++ - '0' ; *s < '9' && *s >= '0' ; ) {
  1213.                     systimeout *= 10;
  1214.                     systimeout += *s++ - '0';
  1215.                 }
  1216.                 s--; /* incremented later - before next time round loop */
  1217.                 printmsg(3, "expect timeout set to %hd", systimeout);
  1218.                 break;
  1219. #endif Upgrade
  1220.             default:
  1221.                   swrite( s, 1 );
  1222.                   if (pace) paceit();
  1223.             }
  1224.             last = '\0';
  1225.         }
  1226.         else if (last == '^') {
  1227.             ctlchar = *s & 0x1f;
  1228.             swrite(&ctlchar, 1);
  1229.               if (pace) paceit();
  1230.             last = '\0';
  1231.         }    
  1232.         else if (*s != '\\' && *s != '^') {
  1233.               swrite( s, 1 );
  1234.               if (pace) paceit();
  1235.         }
  1236.         else {
  1237.             last = *s;
  1238.         }
  1239.         s++;
  1240.     }
  1241.     return( nocr );
  1242. }
  1243.  
  1244. /***
  1245.  *   void sendthem(str)   send line of login sequence
  1246.  *         char *str;
  1247.  *
  1248.  *   return codes:  none
  1249.  */
  1250.  
  1251. void sendstr(char *str)
  1252. {
  1253.     int nw, ns;
  1254.     int nulls = 3;
  1255.  
  1256.     printmsg( 2, "sending %s", str );
  1257.  
  1258. #ifdef BREAK
  1259.     if (prefix("BREAK", str)) {
  1260.         sscanf(&str[5], "%1d", &nulls);
  1261.         if (nulls <= 0 || nulls > 10)
  1262.             nulls = 3;
  1263.         /* send break */
  1264.         (*currentConnection->Break)(nulls);
  1265.         return;
  1266.     }
  1267. #endif BREAK
  1268.  
  1269.     if ( strcmp(str, "EOT") == SAME ) {
  1270.         swrite(EOTMSG, strlen(EOTMSG));
  1271.         return;
  1272.     } else if (strcmp(str, "P_EVEN") == SAME) {
  1273.         (*currentConnection->SetParity)(data7, evenParity);
  1274.         return;
  1275.     } else if (strcmp(str, "P_ODD") == SAME) {
  1276.         (*currentConnection->SetParity)(data7, oddParity);
  1277.         return;
  1278.     } else if (strcmp(str, "P_NONE") == SAME) {
  1279.         (*currentConnection->SetParity)(data8, noParity);
  1280.         return;
  1281.     }        
  1282.  
  1283.     if ( strcmp(str,"\"\"") == SAME )
  1284.         *str = '\0';
  1285.         /*fprintf(stderr,"'%s'\n",str);*/
  1286.  
  1287.     if ( strcmp(str,"") != SAME ) {
  1288.         if (!writestr(str)) {
  1289.             swrite ("\r", 1);
  1290.         }
  1291.     }
  1292.     else {
  1293.         swrite("\r", 1);
  1294.     }
  1295.     return;
  1296. }
  1297.  
  1298. int
  1299. sendexpect(char *s, char *e, long int timeout) {
  1300.  
  1301.     sendstr(s);
  1302.     
  1303. #ifdef Upgrade
  1304.     if(systimeout > 0)
  1305.         return(expectstr(e, systimeout));
  1306. #endif Upgrade
  1307.  
  1308.     return(expectstr(e, timeout));
  1309. }
  1310.  
  1311. dial(void)
  1312. {
  1313.     int    flg, kk, jj, ll, firstflg;
  1314. #define SPEEDBUF 10
  1315.     char    buf[10], *prsend;
  1316.  
  1317.     char *exp;
  1318.     char *alternate;
  1319.     int    ok;
  1320.     int i;
  1321.     int dialpause;
  1322.     static char HayesInitString[] = "\\p\\dAAATQ0V1E0";
  1323.     long minutes_to_sleep;
  1324.  
  1325. #ifdef Upgrade
  1326.     char number[128];
  1327.     char dialstring[256];
  1328.  
  1329.     if ( strcmp( flds[FLD_TYPE], "VADIC" ) == SAME ) {
  1330.         if (rmtname[0] != 0) printmsg( 0, "Dialing host %s", rmtname );
  1331.         if (line(device, speed, NULL ))
  1332.             return( FALSE );
  1333.     
  1334.         (*currentConnection->AllowInterrupts)(TRUE);
  1335.         printmsg( 2, "vadic: autobauding" );
  1336.         if ( sendexpect( "\005\\d", "*", 2 ) != TRUE &&
  1337.          sendexpect( "\005\\d", "*", 2 ) != TRUE ) {
  1338.             printmsg( 0, "vadic: no response to autobaud" );
  1339.             return( FALSE);
  1340.         }
  1341.         printmsg( 1, "vadic: got modem response" );
  1342.     
  1343.         if (sendexpect ("dial", "NUMBER?", 5) != TRUE ) {
  1344.             printmsg( 2, "vadic: dial command rejected" );
  1345.             sendstr("I\dIDLE\\r");
  1346.             return( FALSE);
  1347.         }
  1348.         
  1349.         strcpy(number, "\\d");
  1350.         strcat(number, phone);
  1351.         strcat(number, "\\r\\d");
  1352.         if ( sendexpect(number, "DIALING...•NO DIAL TONE", 5) != TRUE ) {
  1353.             printmsg( 0, "vadic: could not initiate dial" );
  1354.             sendstr("I\dIDLE\\r");
  1355.             return(FALSE);
  1356.         }
  1357.     
  1358.         if ( sendexpect( "\\d\\c", "ON LINE•BUSY•FAILED CALL", 40 ) == TRUE ) {
  1359.             printmsg( 3, "vadic: ON LINE" );
  1360.             return( TRUE );
  1361.         }
  1362.         else {
  1363.             sendstr("I\dIDLE\\r");
  1364.             return( FALSE );
  1365.         }
  1366.     }
  1367.  
  1368. #endif
  1369.  
  1370.     if ( strncmp( flds[FLD_TYPE], "HAYES", 5 ) != SAME ) {
  1371.         printmsg( 0, "dial: unsupported dialer %s", flds[FLD_TYPE] );
  1372.         return( FALSE );
  1373.     }
  1374.  
  1375.     if (rmtname[0] != 0) printmsg( 0, "Dialing host %s", rmtname );
  1376.     if (openline(device, speed, NULL ))
  1377.         return( FALSE );
  1378.     
  1379.     if (flds[FLD_TYPE][5] == '*') {
  1380.         useHardwareFlowControl = TRUE;
  1381.         (*currentConnection->SetFlowCtl)(FALSE, TRUE);
  1382.     }
  1383.  
  1384.     (*currentConnection->AllowInterrupts)(TRUE);
  1385.     
  1386.     strcpy(dialstring, HayesInitString);
  1387.     if (flds[FLD_TYPE][5] != '\0' && flds[FLD_TYPE][6] != '\0') { /* for HAYES+ and HAYES! */
  1388.         strcat(dialstring, flds[FLD_TYPE]+6);
  1389.     }
  1390.     printmsg( 2, "hayes: autobauding" );
  1391.     if ( sendexpect( dialstring, "OK", 2 ) != TRUE &&
  1392.          sendexpect( dialstring, "OK", 2 ) != TRUE) {
  1393.         sendexpect( "\\d\\p+++\\c", "OK", 2 );
  1394.         if ( sendexpect( "\\pAAATZ", "OK", 2 ) != TRUE ||
  1395.              sendexpect( dialstring, "OK", 2 ) != TRUE) {
  1396.             printmsg(0, "hayes: could not get modem's attention");
  1397.             return( FALSE);
  1398.         }
  1399.     }
  1400.     printmsg( 1, "hayes: got modem response" );
  1401. /*    zzz(1); */
  1402.     
  1403.     strcpy(dialstring, "\\pAAAT");    
  1404.     
  1405.     if (strcmp(phone, "-") == SAME | strcmp(phone, "@") == SAME) {
  1406.         strcat(dialstring, "S0=1");
  1407.         sscanf(sleeptime, "%ld", &minutes_to_sleep);
  1408.         if (minutes_to_sleep < 1) minutes_to_sleep = 1;
  1409.         dialpause = minutes_to_sleep * 60;
  1410.     } else {
  1411.         if (isdigit(*phone)) {
  1412.             strcat(dialstring, "DT");
  1413.         }
  1414.         strcat(dialstring, phone);
  1415.         dialpause = 120;
  1416.     }
  1417.  
  1418.     if ( sendexpect( dialstring, "CONNECT•BUSY•NO CARRIER•NO DIAL TONE•NO DIALTONE", dialpause ) == TRUE ) {
  1419.         printmsg( 3, "hayes: got CONNECT" );
  1420.  
  1421.         if ( flds[FLD_TYPE][5] != '!' && flds[FLD_TYPE][5] != '*') {
  1422.             if (sread(buf, 1, 1) == 1 && *buf == ' ') {
  1423.                 i = 0;
  1424.                 while (i < SPEEDBUF) {
  1425.                     if (sread( buf+i, 1, 1 ) != 1 || ! isdigit(buf[i]) ) {
  1426.                         break;
  1427.                     }
  1428.                     i++;
  1429.                 }
  1430.                 if (i > 0) {
  1431.                     buf[i] = '\0';
  1432.                     printmsg( 3, "hayes: speed select %s", buf );
  1433.                     /* set speed appropriately */
  1434.                     (*currentConnection->Speed) ( buf );
  1435.                 }
  1436.             }
  1437.         }
  1438.         return( TRUE );
  1439.     }
  1440.     else {
  1441.         (*currentConnection->AllowInterrupts)(FALSE);
  1442.         sendexpect("\\r\\d\\pAAATZ", "OK", 4);
  1443.         return( FALSE );
  1444.     }
  1445.  
  1446. }
  1447.  
  1448.  
  1449. /*
  1450. **
  1451. **callup
  1452. ** script processor - nothing fancy!
  1453. */
  1454. callup(void)
  1455. {
  1456.     int    flg, kk, jj, ll, firstflg, err;
  1457.     char    *prsend;
  1458.  
  1459.     char *exp;
  1460.     char *alternate;
  1461.     int    ok;
  1462.     int i;
  1463.  
  1464.     useHardwareFlowControl = FALSE;
  1465.  
  1466.     if (rmtname[0] != 0) printmsg( 0, "Calling %s (%s)", rmtname, callcause );
  1467.     
  1468.     if ( strcmp( flds[FLD_TYPE], "DIR" ) == SAME ) {
  1469.         if (openline(device, speed, phone)) {
  1470.             return ('X');
  1471.         }
  1472. #ifdef NOTDEF
  1473.     } else if (strcmp(flds[FLD_TYPE], "TCP") == SAME) {
  1474.         if ((err = open_tcp_uucp()) != noErr) {
  1475.             if (rmtname[0] != 0) printmsg(0, "TCP open failed, code %d", err);
  1476.             return( 'X' );
  1477.         }
  1478. #endif
  1479.     } else {
  1480.         if ( dial() == FALSE ) {
  1481.             if (rmtname[0] != 0) printmsg(0, "Dial failed");
  1482.             return( 'X' );
  1483.         }
  1484.     }
  1485.  
  1486.     (*currentConnection->AllowInterrupts)(TRUE);
  1487.  
  1488.     for (i = FLD_EXPECT; i < kflds; i+=2) {
  1489.  
  1490.         exp = flds[i];
  1491.         printmsg( 2, "callup: expect %d of %d  \"%s\"", i, kflds, exp );
  1492.  
  1493.         ok = FALSE;
  1494.         while (ok != TRUE) {
  1495.  
  1496.             alternate = index( exp, '-' );
  1497.             if (alternate != (char *)NULL)
  1498.                 *alternate++ = '\0';
  1499. #ifdef Upgrade
  1500.             ok = expectstr(exp, (systimeout > 0 ? systimeout : (10+2*strlen(exp))));
  1501. #else Upgrade
  1502.             ok = expectstr( exp, 10+2*strlen(exp) );
  1503. #endif Upgrade
  1504.  
  1505.             printmsg( 2, "got %s", ok != TRUE ? "?" : "that" );
  1506.  
  1507.             if ( ok == TRUE ) {
  1508.                 printmsg( 2, "got that" );
  1509.                 break;
  1510.             }
  1511.  
  1512.             if ( alternate == (char *)NULL ) {
  1513.                 printmsg( 0, "Login failed" );
  1514.                 return( 'X' );
  1515.             }
  1516.  
  1517.             exp = index( alternate, '-' );
  1518.             if ( exp != (char *)NULL )
  1519.                 *exp++ = '\0';
  1520.  
  1521.             printmsg( 1, "send alternate" );
  1522.  
  1523.             sendstr( alternate );
  1524.         }
  1525.  
  1526.     if (i+1 < kflds) {
  1527.         printmsg( 2, "callup: send %d of %d  \"%s\"", i+1, kflds, flds[i+1] );
  1528. #ifdef MULTIFINDER
  1529.         {
  1530.           long Last_Ticks;
  1531.           int status = 0;
  1532.         
  1533.           Last_Ticks = Ticks;
  1534.           while (Ticks-Last_Ticks < 60)
  1535.             if (Check_Events(15)) {
  1536.               printmsg( 0, "Call cancelled by operator" );
  1537.               hangup();
  1538.               (*currentConnection->Close)(TRUE);
  1539.               return( 'X' );
  1540.             }
  1541.         }
  1542. #else
  1543.         zzz(1);
  1544. #endif
  1545.         sendstr(flds[i+1]);
  1546.     }
  1547.     }
  1548.     printmsg( 0, "Connected");
  1549.     return('P');
  1550.  
  1551. }
  1552.  
  1553. /**/
  1554. /*
  1555. **
  1556. **      slowrite
  1557. ** comunication slow write. needed for auto-baud modems
  1558. */
  1559. /*slowrite(st)
  1560. register char    *st;
  1561. {
  1562.     int    len, j;
  1563.     char    c;
  1564.     len = strlen(st);
  1565.     printmsg( 2, "sent %s", st );
  1566.     for (j = 0; j < len; j++) {
  1567.         swrite(&st[j], 1);
  1568.         ddelay(80000);
  1569.     }
  1570. }
  1571. */
  1572.  
  1573. /**/
  1574. /*
  1575. **
  1576. **scandir
  1577. **
  1578. */
  1579.  
  1580. #include "ndir.h"
  1581.  
  1582.  
  1583. /*    scandir
  1584.  
  1585.     scan work dir for C. files matching current remote host (rmtname)
  1586.  
  1587.     return
  1588.  
  1589.         A    - abort
  1590.         Y    - can't open file
  1591.         S    - ok
  1592.         Q    - no files
  1593.  
  1594. */
  1595. scandir(void)
  1596. {
  1597.     int    fn, len, i;
  1598.     char    cname[40], mappedname[40], tmp[132];
  1599.  
  1600.     DIR *dirp;
  1601.     struct direct *dp;
  1602.  
  1603.     if ((dirp = opendir( spooldir )) == (DIR *)NULL ) {
  1604.         fprintf( stderr, "couldn't open dir %s\n", spooldir );
  1605.         return( 'A' );
  1606.     }
  1607. #ifdef Upgrade
  1608.     sprintf(cname, "%s%s", CALLFILE, rmtname);
  1609. #else Upgrade
  1610.     sprintf(cname, CALLFILE, rmtname);
  1611. #endif Upgrade
  1612.     len = strlen(cname);
  1613.     if (len > 9) len = 9;
  1614.     while ((dp = readdir(dirp)) != (struct direct *)NULL) {
  1615.         printmsg( 4, "scandir: %s", dp->d_name );
  1616.         strcpy(mappedname, dp->d_name);
  1617.         unmapMacCaseness(mappedname);
  1618.         if ( strncmp( cname, dp->d_name, len ) == SAME ||
  1619.              strncmp( cname, mappedname, len) == SAME) {
  1620.             printmsg( 4, "scandir: match!!" );
  1621.             strcpy(cfile, dp->d_name);
  1622. #ifdef Upgrade
  1623.             /* don't forget to close the last cfile */
  1624.             if (fw != (FILE *)NULL) {
  1625.                 fclose(fw);
  1626.                 fw = (FILE *)NULL;
  1627.             }
  1628. #endif Upgrade
  1629.             if ((fw = FOPEN( cfile, "r", 't' )) == (FILE *)NULL ) {
  1630.                 printmsg(4, "scandir: could not open file '%s'", cfile );
  1631.                 getcwd(tmp, sizeof tmp);
  1632.                 printmsg(4, "scandir: current working directory was '%s'", tmp );
  1633.                 closedir( dirp );
  1634.                 return('Y');
  1635.             }
  1636.             closedir( dirp );
  1637.             strcpy(callcause, "work pending");
  1638.             return('S');
  1639.         }
  1640.     }
  1641.     closedir( dirp );
  1642.     printmsg(4, "scandir: no work files");
  1643.     return('Q');
  1644.  
  1645. }
  1646.  
  1647.  
  1648. /**/
  1649. /*
  1650. **
  1651. **dscandir
  1652. ** scan the directory
  1653. */
  1654.  
  1655. dscandir(void)
  1656. {
  1657.     int    fn, len, i;
  1658.     char    cname[40], tmp[132], gotname[40];
  1659.  
  1660.     DIR *dirp;
  1661.     struct direct *dp;
  1662.  
  1663.  
  1664.     if ((dirp = opendir( spooldir )) == (DIR *)NULL ) {
  1665.         printmsg( 0, "** couldn't open dir %s\n", spooldir );
  1666.         return(-1);
  1667.     }
  1668.     gotname[0] = 0;
  1669. #ifdef Upgrade
  1670.  
  1671.     /* we probably want ALL X. files to be processed every chance we get
  1672.      * in order to pick up any left behind by crashes before they could
  1673.      * be dealt with. In any case the #else Upgrade code was incorrect
  1674.      * and this fixes that A.S.
  1675.      */
  1676.      
  1677. # ifndef TOORESTRICTIVE
  1678.     strcpy(cname, XQTFILE);
  1679. # else TOORESTRICTIVE
  1680.     sprintf(cname, "%s%s", XQTFILE, rmtname); /* may be too restrictive */
  1681. # endif TOORESTRICTIVE
  1682.  
  1683. #else Upgrade
  1684.     sprintf(cname, XQTFILE, rmtname); /* sprintf(cname,"c%.4s",rmtname); */
  1685. #endif Upgrade
  1686. /*
  1687.     Modified this loop for 3.0d3 to take into account the fact that the
  1688.     names of inbound X. files have gone through a reversable name-conversion
  1689.     process which may change their sort ordering.  The loop now runs through
  1690.     all filenames in the directory, reverses the name-conversion, and picks
  1691.     the X. file with the lowest-sorting name after the reverse conversion.
  1692. */
  1693.     len = strlen(cname);
  1694.     while ((dp = readdir(dirp)) != (struct direct *)NULL) {
  1695.         printmsg( 4, "dscandir: file = %s cname = %s", dp->d_name, cname );
  1696.         unmapMacCaseness(cname);
  1697.         if ( strncmp( cname, dp->d_name, len ) == SAME ) {
  1698.             if (gotname[0] == 0 || strcmp(dp->d_name, gotname) < 0) {
  1699.                 strcpy(gotname, dp->d_name);
  1700.             }
  1701.         }
  1702.     }
  1703.     closedir( dirp );
  1704.     if (gotname[0]) {
  1705.         printmsg( 4, "dscandir: match!!" );
  1706.         strcpy(cfile, gotname);
  1707.         return( -1 );
  1708.     } else {
  1709.         return( 0 );
  1710.     }
  1711. }
  1712.